package hu.diploma.web.client.pages;

import hu.diploma.web.client.Messages;
import hu.diploma.web.client.proxies.ContactProxy;
import hu.diploma.web.client.service.WebContactService;
import hu.diploma.web.client.service.WebContactServiceAsync;
import hu.diploma.web.shared.ComboBoxItem;
import hu.diploma.web.shared.EnumUtil;
import hu.diploma.web.shared.webvos.AddressWebVo;
import hu.diploma.web.shared.webvos.ContactWebVo;
import hu.diploma.web.shared.webvos.PersonalDataWebvo;
import hu.diploma.web.shared.webvos.StructuredNameWebVo;

import java.util.ArrayList;
import java.util.List;

import com.extjs.gxt.ui.client.Style.HorizontalAlignment;
import com.extjs.gxt.ui.client.Style.Orientation;
import com.extjs.gxt.ui.client.Style.SelectionMode;
import com.extjs.gxt.ui.client.binding.FieldBinding;
import com.extjs.gxt.ui.client.binding.FormBinding;
import com.extjs.gxt.ui.client.data.BaseListLoadConfig;
import com.extjs.gxt.ui.client.data.BaseListLoader;
import com.extjs.gxt.ui.client.event.ButtonEvent;
import com.extjs.gxt.ui.client.event.Events;
import com.extjs.gxt.ui.client.event.GridEvent;
import com.extjs.gxt.ui.client.event.Listener;
import com.extjs.gxt.ui.client.event.SelectionChangedEvent;
import com.extjs.gxt.ui.client.event.SelectionListener;
import com.extjs.gxt.ui.client.store.ListStore;
import com.extjs.gxt.ui.client.util.Margins;
import com.extjs.gxt.ui.client.util.Padding;
import com.extjs.gxt.ui.client.widget.BoxComponent;
import com.extjs.gxt.ui.client.widget.ContentPanel;
import com.extjs.gxt.ui.client.widget.VerticalPanel;
import com.extjs.gxt.ui.client.widget.button.Button;
import com.extjs.gxt.ui.client.widget.form.ComboBox;
import com.extjs.gxt.ui.client.widget.form.ComboBox.TriggerAction;
import com.extjs.gxt.ui.client.widget.form.FormPanel;
import com.extjs.gxt.ui.client.widget.form.TextArea;
import com.extjs.gxt.ui.client.widget.form.TextField;
import com.extjs.gxt.ui.client.widget.grid.ColumnConfig;
import com.extjs.gxt.ui.client.widget.grid.ColumnData;
import com.extjs.gxt.ui.client.widget.grid.ColumnModel;
import com.extjs.gxt.ui.client.widget.grid.Grid;
import com.extjs.gxt.ui.client.widget.grid.GridCellRenderer;
import com.extjs.gxt.ui.client.widget.grid.filters.GridFilters;
import com.extjs.gxt.ui.client.widget.grid.filters.StringFilter;
import com.extjs.gxt.ui.client.widget.layout.AccordionLayout;
import com.extjs.gxt.ui.client.widget.layout.FitLayout;
import com.extjs.gxt.ui.client.widget.layout.RowData;
import com.extjs.gxt.ui.client.widget.layout.RowLayout;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayout;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayout.VBoxLayoutAlign;
import com.extjs.gxt.ui.client.widget.layout.VBoxLayoutData;
import com.extjs.gxt.ui.client.widget.table.NumberCellRenderer;
import com.extjs.gxt.ui.client.widget.toolbar.PagingToolBar;
import com.google.gwt.core.client.GWT;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Widget;

public class ContactsPage extends ContentPanel {

	private static ContactsPage instanse;
	private final Messages messages = GWT.create(Messages.class);
	WebContactServiceAsync personService = GWT.create(WebContactService.class);

	ContactWebVo selectedPersonWebVo;
	private final ContentPanel formPanel = new ContentPanel();
	private ListStore<ContactWebVo> store;
	private BaseListLoader loader;

	public ContactsPage() {

		setLayout(new RowLayout(Orientation.HORIZONTAL));
		setSize(1200, 800);
		setFrame(true);
		setHeaderVisible(false);
		ContentPanel cp = new ContentPanel();
		cp.setLayout(new FitLayout());
		cp.setHeading(messages.contacts());

		final Grid<ContactWebVo> grid = createGrid();

		grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
		grid.getSelectionModel().addListener(Events.SelectionChange,
				new Listener<SelectionChangedEvent<ContactWebVo>>() {

					public void handleEvent(SelectionChangedEvent<ContactWebVo> be) {

						selectedPersonWebVo = be.getSelectedItem();
						createForm();
					}

				});
		cp.add(grid);

		cp.setButtonAlign(HorizontalAlignment.LEFT);
		cp.addButton(new Button(messages.create(), new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				ContactWebVo model = new ContactWebVo();
				StructuredNameWebVo nameWebVo = new StructuredNameWebVo();
				nameWebVo.setDisplayName("Ismeretlen");
				model.setNameWebVo(nameWebVo);
				model.setPersonalDatas(new ArrayList<PersonalDataWebvo>());
				model.setDisplayName("Ismeretlen");

				ArrayList<AddressWebVo> addressWebVos = new ArrayList<AddressWebVo>();
				addressWebVos.add(new AddressWebVo());
				model.setAddressWebVos(addressWebVos);
				store.add(model);
				store.commitChanges();
			}
		}));
		cp.addButton(new Button(messages.delete(), new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				personService.deletePerson(selectedPersonWebVo, new AsyncCallback<Void>() {

					public void onSuccess(Void result) {
						store.remove(selectedPersonWebVo);

					}

					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}
				});
			}

		}));
		cp.addButton(new Button(messages.save(), new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				personService.updatePerson(selectedPersonWebVo, new AsyncCallback<ContactWebVo>() {

					public void onSuccess(ContactWebVo result) {
						selectedPersonWebVo = result;
						loader.load();
					}

					public void onFailure(Throwable caught) {
						// TODO Auto-generated method stub

					}
				});
			}
		}));
		// add(cp, new RowData(.5, 1, new Margins(4)));
		// add(formPanel, new RowData(.5, 1, new Margins(4, 0, 4, 0)));
		createForm();

		add(cp, new RowData(0.7, 1, new Margins(4)));
		ContentPanel panel = new ContentPanel();
		VBoxLayout layout = new VBoxLayout();
		layout.setPadding(new Padding(5));
		layout.setVBoxLayoutAlign(VBoxLayoutAlign.STRETCH);
		panel.setLayout(layout);
		Image image = new Image("contact.jpg");
		image.setPixelSize(150, 150);
		ContentPanel contentPanel = new ContentPanel();
		contentPanel.setHeaderVisible(false);

		contentPanel.add(image);
		panel.add(contentPanel, new VBoxLayoutData(new Margins(0, 0, 5, 0)));
		panel.add(formPanel, new VBoxLayoutData(new Margins(0, 0, 5, 0)));

		formPanel.setHeading(messages.personalData());
		formPanel.setBodyBorder(true);

		add(panel, new RowData(0.3, 1, new Margins(4, 0, 4, 0)));

	}

	private void createForm() {

		ContentPanel panel = new ContentPanel();
		panel.setHeaderVisible(false);
		panel.setBodyBorder(true);
		panel.setHeight(400);
		if (selectedPersonWebVo == null) {
			panel.collapse();
		}
		AccordionLayout layout = new AccordionLayout();
		layout.setAutoWidth(true);
		panel.setLayout(layout);

		ContentPanel cp = new ContentPanel();

		cp.setAnimCollapse(true);
		cp.setHeading(messages.name());
		cp.setLayout(new FitLayout());

		panel.add(cp);
		cp.add(createStructuredNamePanel());

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.phone());
		panel.add(cp);
		cp.add(personalDataPanel("PHONE"));

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.email());
		panel.add(cp);
		cp.add(personalDataPanel("EMAIL"));

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.website());
		panel.add(cp);
		cp.add(personalDataPanel("WEBSITE"));

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.event());
		panel.add(cp);
		cp.add(personalDataPanel("EVENT"));

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.Im());
		panel.add(cp);
		cp.add(personalDataPanel("IM"));

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.nickname());
		panel.add(cp);
		cp.add(personalDataPanel("NICKNAME"));

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.address());
		panel.add(cp);
		cp.add(createAddressPanel());

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.organization());
		panel.add(cp);
		cp.add(createOrganisationForm());

		cp = new ContentPanel();
		cp.setAnimCollapse(true);
		cp.setHeading(messages.note());
		panel.add(cp);
		cp.add(createNoteForm());

		formPanel.removeAll();
		formPanel.add(panel);
		this.doLayout();

	}

	private Widget createNoteForm() {
		FormPanel panel = new FormPanel();

		panel.setHeaderVisible(false);
		panel.setLabelSeparator("");
		panel.setFieldWidth(400);
		TextArea note = new TextArea();
		note.setHeight(250);
		note.setName("country");

		FormBinding binding = new FormBinding(panel);

		if (selectedPersonWebVo != null) {

			List<PersonalDataWebvo> pList = selectedPersonWebVo.getPersonalDatas();
			for (PersonalDataWebvo personalDataWebvo : pList) {
				if (personalDataWebvo.getType().equals("NOTE")) {
					binding.bind(personalDataWebvo);
				}
			}
			binding.addFieldBinding(new FieldBinding(note, "value"));

			binding.autoBind();

			panel.add(note);

		}

		return panel;
	}

	private Widget createOrganisationForm() {
		FormPanel panel = new FormPanel();
		panel.setSize(400, 300);
		panel.setHeaderVisible(false);

		TextField<String> organitation = new TextField<String>();
		organitation.setFieldLabel(messages.organization());
		organitation.setName("value");

		TextField<String> title = new TextField<String>();
		title.setFieldLabel(messages.organization_title());
		title.setName("subValue");

		FormBinding binding = new FormBinding(panel);

		if (selectedPersonWebVo != null) {

			List<PersonalDataWebvo> pList = selectedPersonWebVo.getPersonalDatas();
			for (PersonalDataWebvo personalDataWebvo : pList) {
				if (personalDataWebvo.getType().equals("ORGANIZATION")) {
					binding.bind(personalDataWebvo);
				}
			}
			binding.addFieldBinding(new FieldBinding(organitation, "value"));
			binding.addFieldBinding(new FieldBinding(title, "subValue"));

			binding.autoBind();

			panel.add(organitation);
			panel.add(title);

		}

		return panel;
	}

	private Widget createAddressPanel() {
		FormPanel panel = new FormPanel();
		panel.setSize(400, 300);
		panel.setHeaderVisible(false);

		TextField<String> country = new TextField<String>();
		country.setFieldLabel(messages.country());
		country.setName("country");

		TextField<String> state = new TextField<String>();
		state.setFieldLabel(messages.state());
		state.setName("state");

		TextField<String> city = new TextField<String>();
		city.setFieldLabel(messages.city());
		city.setName("city");

		TextField<String> street = new TextField<String>();
		street.setFieldLabel(messages.street());
		street.setName("street");

		TextField<String> postalCode = new TextField<String>();
		postalCode.setFieldLabel(messages.postalCode());
		postalCode.setName("postalCode");

		TextField<String> pobox = new TextField<String>();
		pobox.setFieldLabel(messages.pobox());
		pobox.setName("pobox");

		FormBinding binding = new FormBinding(panel);

		if (selectedPersonWebVo != null) {

			binding.bind(selectedPersonWebVo.getAddressWebVos().get(0));

			binding.addFieldBinding(new FieldBinding(pobox, "pobox"));
			binding.addFieldBinding(new FieldBinding(postalCode, "postalCode"));
			binding.addFieldBinding(new FieldBinding(city, "city"));
			binding.addFieldBinding(new FieldBinding(state, "state"));
			binding.addFieldBinding(new FieldBinding(country, "country"));
			binding.addFieldBinding(new FieldBinding(street, "street"));

			binding.autoBind();

			panel.add(country);
			panel.add(state);
			panel.add(city);
			panel.add(street);
			panel.add(postalCode);
			panel.add(pobox);

		}

		return panel;
	}

	private FormPanel createStructuredNamePanel() {
		FormPanel panel = new FormPanel();
		panel.setSize(400, 300);
		panel.setHeaderVisible(false);

		TextField<String> displayName = new TextField<String>();
		displayName.setFieldLabel(messages.displayName());
		displayName.setName("displayName");

		TextField<String> familName = new TextField<String>();
		familName.setFieldLabel(messages.familName());
		familName.setName("familName");

		TextField<String> givenName = new TextField<String>();
		givenName.setFieldLabel(messages.givenName());
		givenName.setName("givenName");

		TextField<String> middleName = new TextField<String>();
		middleName.setFieldLabel(messages.middleName());
		middleName.setName("middleName");

		TextField<String> preixName = new TextField<String>();
		preixName.setFieldLabel(messages.preixName());
		preixName.setName("preixName");

		FormBinding binding = new FormBinding(panel);

		if (selectedPersonWebVo != null) {

			binding.bind(selectedPersonWebVo.getNameWebVo());

			binding.addFieldBinding(new FieldBinding(displayName, "displayName"));
			binding.addFieldBinding(new FieldBinding(familName, "familName"));
			binding.addFieldBinding(new FieldBinding(givenName, "givenName"));
			binding.addFieldBinding(new FieldBinding(middleName, "middleName"));
			binding.addFieldBinding(new FieldBinding(preixName, "preixName"));

			binding.autoBind();

			panel.add(displayName);
			panel.add(preixName);
			panel.add(familName);
			panel.add(middleName);
			panel.add(givenName);

		}

		return panel;
	}

	private FormPanel personalDataPanel(final String type) {
		FormPanel panel = new FormPanel();
		panel.setHeaderVisible(false);

		final VerticalPanel verticalPanel = new VerticalPanel();

		if (selectedPersonWebVo != null) {

			List<PersonalDataWebvo> pList = selectedPersonWebVo.getPersonalDatas();
			if ((pList != null) && (pList.size() > 0)) {
				for (PersonalDataWebvo personalDataWebvo : pList) {
					if (personalDataWebvo.getType().equals(type)) {
						final FormPanel horizontalPanel = createpersonalDataForm(personalDataWebvo, type);
						verticalPanel.add(horizontalPanel);
					}
				}
			}
			panel.add(verticalPanel);
			VerticalPanel newPanel = new VerticalPanel();
			newPanel.add(new Button(messages.newElem(), new SelectionListener<ButtonEvent>() {
				@Override
				public void componentSelected(ButtonEvent ce) {
					PersonalDataWebvo personalDataWebvo = new PersonalDataWebvo();

					selectedPersonWebVo.getPersonalDatas().add(personalDataWebvo);
					verticalPanel.add(createpersonalDataForm(personalDataWebvo, type));
					doLayout();
				}
			}));
			panel.add(newPanel);

		}
		return panel;
	}

	private FormPanel createpersonalDataForm(final PersonalDataWebvo personalDataWebvo, String type) {
		final FormPanel panel = new FormPanel();

		panel.setHeaderVisible(false);
		panel.setLayout(new RowLayout(Orientation.HORIZONTAL));
		panel.setSize(350, 40);
		ListStore<ComboBoxItem> phone = new ListStore<ComboBoxItem>();
		phone.add(EnumUtil.getPhoneComboBoxValue(type));

		personalDataWebvo.setSubType(EnumUtil.getPhoneComboBoxValue(personalDataWebvo.getSubTypeText()));

		ComboBox<ComboBoxItem> combo = new ComboBox<ComboBoxItem>();
		combo.setDisplayField("text");
		combo.setName("subType");
		combo.setStore(phone);
		combo.setTypeAhead(true);
		combo.setTriggerAction(TriggerAction.ALL);
		combo.setWidth(90);

		panel.add(combo);

		TextField<String> value = new TextField<String>();
		value.setName("value");
		value.setFieldLabel(messages.email());
		panel.add(value);

		panel.add(new Button(messages.delete(), new SelectionListener<ButtonEvent>() {
			@Override
			public void componentSelected(ButtonEvent ce) {
				((VerticalPanel) panel.getParent()).remove(panel);
				selectedPersonWebVo.getPersonalDatas().remove(personalDataWebvo);
			}
		}));

		FormBinding binding = new FormBinding(panel);
		if (selectedPersonWebVo != null) {

			binding.bind(personalDataWebvo);

			binding.addFieldBinding(new FieldBinding(value, "value"));
			binding.addFieldBinding(new FieldBinding(combo, "subType"));

			binding.autoBind();

		}

		return panel;
	}

	private Grid<ContactWebVo> createGrid() {
		final NumberFormat currency = NumberFormat.getCurrencyFormat();
		final NumberFormat number = NumberFormat.getFormat("0.00");
		final NumberCellRenderer<Grid<ContactWebVo>> numberRenderer = new NumberCellRenderer<Grid<ContactWebVo>>(
				currency);
		GridFilters filters = new GridFilters();
		filters.setLocal(true);
		StringFilter phoneFilter = new StringFilter("phone");
		StringFilter emailFilter = new StringFilter("email");
		StringFilter nameFilter = new StringFilter("displayName");

		filters.addFilter(phoneFilter);
		filters.addFilter(emailFilter);
		filters.addFilter(nameFilter);

		List<ColumnConfig> configs = new ArrayList<ColumnConfig>();

		ColumnConfig column = new ColumnConfig();

		column = new ColumnConfig();
		column.setId("symbol");
		column.setHeader(messages.image());
		column.setWidth(35);

		column.setRenderer(buttonRenderer);
		configs.add(column);

		column = new ColumnConfig();
		column.setId("displayName");
		column.setHeader(messages.name());
		column.setWidth(200);
		column.setStyle("vertical-align:middle;");
		configs.add(column);

		column = new ColumnConfig();
		column.setId("email");
		column.setHeader(messages.email());
		column.setWidth(200);
		column.setStyle("vertical-align:middle;");
		configs.add(column);

		column = new ColumnConfig();
		column.setId("phone");
		column.setHeader(messages.phone());
		column.setWidth(200);
		column.setStyle("vertical-align:middle;");
		configs.add(column);

		column = new ColumnConfig();
		column.setId("groups");
		column.setHeader(messages.group_header());
		column.setWidth(200);
		column.setStyle("vertical-align:middle;");
		configs.add(column);

		loader = new BaseListLoader(new ContactProxy());
		loader.setRemoteSort(false);

		store = new ListStore<ContactWebVo>(loader);
		BaseListLoadConfig loadConfig = new BaseListLoadConfig();

		loader.load(loadConfig);

		// store.setMonitorChanges(true);

		ColumnModel columnModel = new ColumnModel(configs);

		Grid<ContactWebVo> grid = new Grid<ContactWebVo>(store, columnModel);
		grid.getView().setEmptyText(messages.emtyGrid());
		grid.setBorders(false);
		grid.setAutoExpandColumn("email");
		grid.setWidth(800);
		grid.setLoadMask(true);
		grid.addPlugin(filters);

		// cp.add(grid);

		final PagingToolBar toolBar = new PagingToolBar(25);
		// toolBar.bind(loader);

		// cp.setBottomComponent(toolBar);
		return grid;
	}

	GridCellRenderer<ContactWebVo> buttonRenderer = new GridCellRenderer<ContactWebVo>() {

		private boolean init;

		public Object render(final ContactWebVo model, String property, ColumnData config, final int rowIndex,
				final int colIndex, ListStore<ContactWebVo> store, Grid<ContactWebVo> grid) {
			Image image = new Image("contact.jpg");
			image.setSize("30px", "30px");
			if (!init) {
				init = true;
				grid.addListener(Events.ColumnResize, new Listener<GridEvent<ContactWebVo>>() {

					public void handleEvent(GridEvent<ContactWebVo> be) {
						for (int i = 0; i < be.getGrid().getStore().getCount(); i++) {
							if ((be.getGrid().getView().getWidget(i, be.getColIndex()) != null)
									&& (be.getGrid().getView().getWidget(i, be.getColIndex()) instanceof BoxComponent)) {
								((BoxComponent) be.getGrid().getView().getWidget(i, be.getColIndex())).setWidth(be
										.getWidth() - 5);
							}
						}
					}
				});
			}

			return image;
		}
	};

	public static ContactsPage getWidget() {

		if (instanse == null) {
			instanse = new ContactsPage();
		}
		return instanse;
	}
}